<template>
  <div class="content-container" :style="{'--leftWidthOffset': leftWidthOffset + 'px',...themeVar}">
    <div class="left_pane">
      <div class="left-title">字典类型</div>
      <div class="search-op-box">
        <el-input
            placeholder="请输入字典名称"
            style="width: 100%"
            v-model="params.keywords"
            :suffix-icon="Search"
            clearable
            @keyup.enter="queryDictTypeList"
            @input="queryDictTypeList"
        />
        <el-button @click="openAddDictTypeForm" class="ml10 button_base_style" :icon="FolderAdd" type="primary">
          新增
        </el-button>
        <el-button plain @click="refreshDictCache" class="ml10 button_base_style" :icon="RefreshLeft" type="primary">
          刷新缓存
        </el-button>
      </div>
      <el-scrollbar
          class="dict_list"
          v-loading="dictTypeLoading"
          v-infinite-scroll="loadMoreDictType"
          :infinite-scroll-disabled="params.noMore||params.queryStatus"
      >
        <template v-for="(dict, index) in dictTypeList" :key="dict.dictType">
          <div class="dict_group_title system_dict" v-if="dict?.isEnumDict&&index===0">系统字典</div>
          <div
              class="dict_item"
              :class="{ active: dict.dictType === selectDict.dictType ,'enum_dict': dict?.isEnumDict}"
              @click="handleClickDictType(dict)"
          >
            <span>{{ dict.dictName }}</span>
            <span>{{ dict.dictType }}</span>
            <div>
              <el-button :icon="DocumentCopy" @click.stop="copyText(dict.dictType)"/>
              <el-button :icon="Edit" @click.stop="openEditDictTypeForm(dict)"/>
              <el-button
                  :icon="Delete"
                  class="ml10"
                  @click.stop="handleDictTypeDelete(dict)"
              />
              <!-- <el-tooltip content="系统字典" placement="right" />-->
            </div>
          </div>
          <div class="dict_group_title" v-if="dict?.isLastEnumDict&&dictTypeList.length-1>index">基础字典</div>
        </template>
      </el-scrollbar>
      <div class="export_button">
        <el-button @click="exportDictData" class="button_base_style" :icon="Download" type="primary">
          导出
        </el-button>
      </div>
      <div class="resize" @mousedown.left="startDrag"/>
    </div>
    <div class="right_table">
      <div class="right_table_title">{{ selectDict?.dictName || '字典数据' }}</div>
      <el-row>
        <el-button @click="openAddDictDataForm" class="button_base_style" :icon="FolderAdd" type="primary">
          新增
        </el-button>
        <div style="flex: 1"/>
        <el-tooltip content="刷新" placement="top">
          <el-button class="refresh_button" :icon="Refresh" circle @click.stop="refreshDictData"/>
        </el-tooltip>
      </el-row>
      <el-table
          ref="dictTable"
          border
          v-loading="dictDataLoading"
          :data="dictDataList"
          header-cell-class-name="table_header_cell"
          cell-class-name="table_cell"
          row-class-name="table_row"
          max-height="calc(100% - 40px - 10px)"
      >
        <el-table-column prop="dictType" label="字典类型" show-overflow-tooltip/>
        <el-table-column prop="dictLabel" label="字典标签" show-overflow-tooltip/>
        <!--        <el-table-column prop="listClass" label="样式类型" show-overflow-tooltip />-->
        <el-table-column prop="dictValue" label="数据值" show-overflow-tooltip/>
        <el-table-column label="回显样式">
          <template #default="scope">
            <dict-tag :options="packageData(scope.row)" :value="scope.row.dictValue"/>
          </template>
        </el-table-column>
        <el-table-column prop="sort" label="排序" show-overflow-tooltip width="70"/>
        <el-table-column prop="createTime" label="创建时间" show-overflow-tooltip width="160"/>
        <el-table-column label="操作" width="160">
          <template #default="scope">
            <div class="operation">
              <el-button
                  v-hasPerm="['system:dict:edit']"
                  size="small"
                  class="el-button--text"
                  :icon="Edit"
                  :style="{color: selectDict.isEnumDict? '#5d5a5a' : ''}"
                  :disabled="selectDict.isEnumDict"
                  @click="openEditDictDataForm(scope.row)"
              >修改
              </el-button>
              <el-button
                  v-hasPerm="['system:dict:delete']"
                  size="small"
                  class="el-button--text"
                  :icon="Delete"
                  :style="{color: selectDict.isEnumDict? '#5d5a5a' : '#F56C6C'}"
                  :disabled="selectDict.isEnumDict"
                  @click="handleDictDataDelete(scope.row)"
              >删除
              </el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <FormDialog
        ref="dictTypeFormDialog"
        :form-props="dictTypeFormProps"
        :top="8"
        :width="40"
        :height="30"
        @save="handleDictTypeAdd"
        @update="handleDictTypeUpdate"
    />


    <FormDialog
        ref="dictDataFormDialog"
        :form-props="dictDataFormProps"
        :top="8"
        :width="40"
        :height="50"
        @save="
        handleDictDataAdd"
        @update="handleDictDataUpdate"
    >
      <template #dialog-title="scope">
        <div style="margin-right: 10px">{{ scope.title }}</div>
        <dict-tag :options="packageData({...scope.row, dictValue: ''})" :value="''"/>
      </template>
    </FormDialog>

  </div>
</template>

<script setup>
import { Delete, DocumentCopy, Download, Edit, FolderAdd, Refresh, RefreshLeft, Search } from '@element-plus/icons-vue'
import { colorScale } from "@/utils/color-adjust.js"

//----表格布局动态变化
const dictTable = useTemplateRef("dictTable")
//监听窗口大小变化
onMounted(() => window.addEventListener('resize', () => dictTable.value?.doLayout()))
onBeforeUnmount(() => window.removeEventListener('resize', () => dictTable.value?.doLayout()))


//----根据字典数据包装dict数据
const packageData = (data) => {
  data.dictLabel = data.dictLabel || '预览标签'
  return [
    {
      label: data.dictLabel,
      value: data.dictValue,
      tagType: data.listClass,
      className: data.cssClass,
    }
  ]
}

async function copyText(text) {
  try {
    await navigator.clipboard.writeText(text)
    $xl.modal.msgSuccess('复制成功')
  } catch {
    // 创建临时textarea元素
    const textarea = document.createElement('textarea')
    textarea.value = text
    document.body.appendChild(textarea)
    // 选择文本
    textarea.select()
    try {
      // 执行复制命令
      document.execCommand('copy')
      $xl.modal.msgSuccess('复制成功')
    } catch (err) {
      $xl.modal.msgError('复制失败:' + err.message)
    }
    // 移除临时元素
    document.body.removeChild(textarea)
  }
}

//----拖拽设置宽度
const dragging = ref(false)
const leftWidthOffset = ref(0)
const startDrag = (event) => {
  if (event.button === 0) {
    dragging.value = true
    document.addEventListener('mousemove', onDragging)
    document.addEventListener('mouseup', endDrag)
  }
}
const onDragging = (event) => {
  if (dragging.value) leftWidthOffset.value += event.movementX
}
const endDrag = () => {
  dragging.value = false
  document.removeEventListener('mousemove', onDragging)
  document.removeEventListener('mouseup', endDrag)
}
document.addEventListener('mousemove', onDragging)
document.addEventListener('mouseup', endDrag)
//-----导出功能
const exportDictData = () => {
  $xl.apis.download('/system/dictType/exportAll', {}, `字典数据_${ new Date().getTime() }.xlsx`)
}
//-----------------------------------字典数据获取------------------------------------------
//----当前选择的字典类型
const selectDict = ref({})
//----字典类型
const dictTypeList = ref([])
const dictTypeLoading = ref(true)
//----字典数据
const dictDataList = ref([])
const dictDataLoading = ref(true)
//----系统字典类型
const systemDictTypeList = ref([])
$xl.apis.getEnumDictTypes().then(res => {
  res.data.forEach(item => item.isEnumDict = true)
  systemDictTypeList.value = res.data
  // 确保在系统字典类型后面加载基础字典类型,通过设置queryStatus为false,开启触底加载
  params.value.queryStatus = false
})
//----基础字典类型
const params = ref({
  pageIndex: 0,
  pageSize: 10,
  keywords: '',
  noMore: false,
  queryStatus: true,
})
// 通过设置pageIndex为0和noMore为false，触发触底加载,初始化数据
const queryDictTypeList = () => {
  $xl.throttle(() => {
    params.value.pageIndex = 0
    params.value.noMore = false
    dictTypeList.value = []
  }, 400, false)
}
//----加载更多基础字典类型
const loadMoreDictType = () => {
  if (params.value.noMore || params.value.queryStatus) return
  params.value.pageIndex++
  params.value.queryStatus = true
  $xl.apis.getDictTypes({
    params: params.value
  }).then(res => {
    if (res.data.current >= res.data.pages && res.data.records.length <= params.value.pageSize) params.value.noMore = true
    // 对于第一次获取数据，将系统字典类型放到第一位
    if (params.value.pageIndex === 1) {
      let enumDictTypesRes
      if (params.value.keywords.length > 0) {
        // 根据关键字过滤出系统字典
        enumDictTypesRes = systemDictTypeList.value.filter(item => item.dictType.includes(params.value.keywords) || item.dictName.includes(params.value.keywords))
      } else enumDictTypesRes = systemDictTypeList.value
      if (enumDictTypesRes.length > 0) {
        enumDictTypesRes = $xl.deepClone(enumDictTypesRes)
        enumDictTypesRes.at(-1).isLastEnumDict = true
        dictTypeList.value.push(...enumDictTypesRes)
      }
      // 确保在系统字典类型后面加载基础字典类型
      dictTypeList.value.push(...res.data.records)
      // 第一次加载数据,默认打开第一个字典类型
      if (dictTypeList.value.length > 0) handleClickDictType(dictTypeList.value[0])
      dictTypeLoading.value = false
    } else dictTypeList.value.push(...res.data.records)
    // 通过设置queryStatus为false,开启触底加载
    params.value.queryStatus = false
  })
}
//----点击字典类型加载字典数据
const handleClickDictType = async (dictType) => {
  selectDict.value = dictType
  dictDataLoading.value = true
  await $xl.apis.getDictDataByType({
    jointUrl: '/' + dictType.dictType
  }).then(res => {
    dictDataList.value = res.data
    dictDataLoading.value = false
  })
}
//----刷新字典数据
const refreshDictData = async () => {
  await handleClickDictType(selectDict.value)
  $xl.modal.msgSuccess('刷新成功')
}
//----刷新字典缓存
const refreshDictCache = () => {
  $xl.apis.refreshDictTypeCache().then(() => $xl.modal.msgSuccess({message: '字典缓存,刷新成功!!!'}))
}

//----------------------------------表单处理--------------------------------------------
const dictTypeFormDialog = useTemplateRef("dictTypeFormDialog")
const dictDataFormDialog = useTemplateRef("dictDataFormDialog")
//---------------------------------表单基础数据----
// 数据标签回显样式
const listClassOptions = [
  {
    value: 'default',
    label: '默认'
  },
  {
    value: 'primary',
    label: '主要'
  },
  {
    value: 'success',
    label: '成功'
  },
  {
    value: 'info',
    label: '信息'
  },
  {
    value: 'warning',
    label: '警告'
  },
  {
    value: 'danger',
    label: '危险'
  }
]
const dictTypeFormProps = computed(() => ([
  {label: '字典名称', prop: 'dictName', type: $formType.input()},
  {label: '字典类型', prop: 'dictType', type: $formType.input()},
  {label: '状态', prop: 'status', type: $formType.radio($dict.normal_disable), default: '0', required: false},
  {label: '备注', prop: 'remark', type: $formType.textarea(), required: false}
]))
const dictDataFormProps = computed(() => ([
  {label: '字典类型', prop: 'dictType', type: $formType.input()},
  {label: '数据标签', prop: 'dictLabel', type: $formType.input()},
  {label: '数据键值', prop: 'dictValue', type: $formType.input()},
  {label: '样式属性', prop: 'cssClass', type: $formType.input(), required: false},
  {label: '显示排序', prop: 'sort', type: $formType.inputNumber(), default: 0, required: false},
  {label: '回显样式', prop: 'listClass', type: $formType.select(listClassOptions), default: 'primary', required: false},
  {label: '状态', prop: 'status', type: $formType.radio($dict.normal_disable), default: '0', required: false},
  {label: '备注', prop: 'remark', type: $formType.textarea(), required: false}
]))
//----------打开新增字典类型表单----
const openAddDictTypeForm = () => {
  dictTypeFormDialog.value.open('新增字典类型')
}
//----------打开修改字典类型表单----
const openEditDictTypeForm = (dictType) => {
  $xl.apis.getDictType({
    jointUrl: '/' + dictType.id
  }).then(response => {
    dictTypeFormDialog.value.open('修改字典类型', response.data)
  })
}

//----------打开新增字典数据表单----
const openAddDictDataForm = () => {
  dictDataFormDialog.value.open('新增字典数据', {dictType: selectDict.value.dictType})
}


//----------打开修改字典数据表单----
const openEditDictDataForm = (dictData) => {
  $xl.apis.getDictData({
    jointUrl: '/' + dictData.id
  }).then(response => {
    dictDataFormDialog.value.open('修改字典数据', response.data)
  })
}


//---------------------------------字典操作----
//-------字典类型新增
const handleDictTypeAdd = (form) => {
  $xl.apis.saveDictType({
    params: form
  }).then(() => {
    params.value.keywords = ''
    queryDictTypeList()
    dictTypeFormDialog.value.close()
  }).catch(err => dictTypeFormDialog.value.close(err))
}
//-------字典类型修改
const handleDictTypeUpdate = (form) => {
  $xl.apis.updateDictType({
    params: form
  }).then(() => {
    params.value.keywords = ''
    queryDictTypeList()
    dictTypeFormDialog.value.close()
  }).catch(err => dictTypeFormDialog.value.close(err))
}
//-------字典类型删除
const handleDictTypeDelete = (dictType) => {
  $xl.modal.confirm('是否确认删除字典编号为"' + dictType.id + '"的数据项？').then(async () => {
    $xl.apis.deleteDictType({
      jointUrl: '/' + dictType.id
    }).then(() => {
      params.value.keywords = ''
      queryDictTypeList()
      $xl.modal.msgSuccess('删除成功')
    })
  })
}
//-------字典数据新增
const handleDictDataAdd = (form) => {
  $xl.apis.saveDictData({
    params: form
  }).then(() => {
    handleClickDictType(selectDict.value)
    dictDataFormDialog.value.close()
  }).catch(err => dictDataFormDialog.value.close(err))
}
//-------字典数据修改
const handleDictDataUpdate = (form) => {
  $xl.apis.updateDictData({
    params: form
  }).then(() => {
    handleClickDictType(selectDict.value)
    dictDataFormDialog.value.close()
  }).catch(err => dictDataFormDialog.value.close(err))
}
//-------字典数据删除
const handleDictDataDelete = (dictData) => {
  $xl.modal.confirm('是否确认删除字典编码为"' + dictData.id + '"的数据项？').then(() => {
    $xl.apis.deleteDictData({
      jointUrl: '/' + dictData.id
    }).then(() => {
      $xl.modal.msgSuccess('删除成功')
      handleClickDictType(selectDict.value)
    })
  }).catch(() => {
  })
}


//-------动态主题颜色
const curTheme = computed(() => $store.settings.theme)
const themeVar = computed(() => ({
  '--team_color': curTheme.value,
  '--button_bc': curTheme.value,
  '--button_hover_bc': colorScale(curTheme.value, {$lightness: 0.2}),
  '--button_active_bc': colorScale(curTheme.value, {$lightness: -0.1}),
  '--button_plain_bc': colorScale(curTheme.value, {$lightness: 0.56}),
  '--button_plain_border': colorScale(curTheme.value, {$lightness: 0.25}),
}))
</script>

<style scoped lang="scss">
@use '@/assets/styles/variables.module' as variables;
@use "sass:color";

$dict_list_line_height: 38px;
$left_pane_width: 25%;

@mixin pane-base-style {
  height: 100%;
  border-radius: 4px;
  background-color: #ffffff;
  border: 1px solid rgb(228, 231, 237);
  padding: 15px;
}

.hasTagsView .app-main .content-container {
  height: calc(100vh - #{variables.$navbar-height} - #{variables.$tags-view-height});
}

.content-container {
  padding: 15px;
  height: calc(100vh - #{variables.$navbar-height});
  display: flex;
  background-color: #f8f8f8;
  user-select: none;

  .ml10 {
    margin-left: 10px !important;
  }

  :deep(.el-row) {
    margin-bottom: 12px;
  }

  :deep(.el-input) {
    --el-input-focus-border-color: var(--team_color);
  }

  :deep(.el-button--primary) {
    --el-button-text-color: #fff;
    --el-button-border-color: var(--team_color);
    --el-button-bg-color: var(--team_color);
    --el-button-active-bg-color: var(--button_active_bc);
    --el-button-hover-bg-color: var(--button_hover_bc);
    --el-button-active-border-color: var(--button_active_bc);
    --el-button-hover-border-color: var(--button_hover_bc);

    &.is-plain {
      --el-button-text-color: var(--team_color);
      --el-button-bg-color: var(--button_plain_bc);
      --el-button-border-color: var(--button_plain_border);
      --el-button-hover-bg-color: var(--team_color);
      --el-button-hover-border-color: var(--team_color);
    }
  }

  .button_base_style {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    line-height: 1;
    height: 30px;
    white-space: nowrap;
    text-align: center;
    transition: .1s;
    user-select: none;
    vertical-align: middle;
    padding: 8px 15px;
    box-sizing: border-box;
    cursor: pointer;


  }
}


.left_pane {
  width: calc(#{$left_pane_width} + var(--leftWidthOffset));
  min-width: 20%;
  max-width: 50%;
  overflow: hidden;
  position: relative;
  @include pane-base-style;

  .left-title {
    font-size: 22px;
    color: #73767a;
    font-weight: 700;
    margin-bottom: 20px;
  }

  .search-op-box {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 10px;
  }

  .resize {
    position: absolute;
    right: 0;
    bottom: 0.5%;
    width: 3px;
    height: 99%;
    cursor: ew-resize;
    /* 鼠标样式 */
  }


  .dict_list {
    height: calc(100% - 40px - 32px - 32px - 20px);
    width: 100%;
    user-select: none;

    .dict_group_title {
      color: var(--team_color);
      margin: 12px 0 12px;
      font-size: 16px;

      &.system_dict {
        //margin-top: 3px;
      }
    }

    .dict_item {
      display: flex;
      flex: 1;
      align-items: center;
      justify-content: space-between;
      font-size: 14px;
      height: #{$dict_list_line_height};
      line-height: #{$dict_list_line_height};
      padding: 0 24px;
      border-radius: 4px;
      cursor: pointer;

      &.enum_dict:hover {
        padding-right: 24px;

        & > span:nth-child(2) {
          display: block;
        }

        & > div {
          display: none;
        }
      }

      :deep(.el-button) {
        border-radius: 0;
        height: #{$dict_list_line_height};
        width: #{$dict_list_line_height};
        line-height: #{$dict_list_line_height};
        margin-bottom: 1px;

        &:hover, &:focus {
          color: var(--team_color);
          border-color: var(--button_plain_border);
          background-color: var(--button_plain_bc);
        }

        &.is-disabled:hover, &.is-disabled:focus {
          color: #a8abb2;
          border-color: #e4e7ed;
          background-color: #ffffff;
          cursor: not-allowed;
        }
      }

      & > span:nth-child(1) {
        color: rgb(96, 98, 102);
        user-select: text;
      }

      & > span:nth-child(2) {
        color: rgb(153, 153, 153);
      }

      & > div {
        display: none;
      }

      &:hover {
        background-color: #f5f7fa;
        padding-right: 16px;

        & > span:nth-child(2) {
          display: none;
        }

        & > div {
          display: block;
        }
      }

      &.active {
        background-color: #f5f7fa;
      }
    }
  }

  .export_button {
    height: 40px;
    line-height: 40px;
    padding: 0 0;
    box-sizing: border-box;
    width: 100%;

    :deep(.el-button) {
      height: 30px;
      padding: 5px 11px;
      font-size: 12px;
      width: 100%;
      border-radius: 5px;
    }
  }
}


.right_table {
  width: calc(100% - #{$left_pane_width} - 8px - var(--leftWidthOffset));
  min-width: calc(50% - 8px);
  max-width: calc(80% - 8px);
  margin-left: 8px;
  overflow: hidden;
  @include pane-base-style;

  .right_table_title {
    font-size: 22px;
    color: #73767a;
    font-weight: 700;
    margin-bottom: 21px;
  }

  .refresh_button {
    width: 32px;
    height: 32px;
    margin-right: 20px;

    &:hover, &:focus {
      color: var(--team_color);
      border-color: var(--button_plain_border);
      background-color: var(--button_plain_bc);
    }

    &:active {
      border-color: var(--team_color);
    }

  }

  .operation {
    display: flex;
    width: 100%;
    justify-content: space-around;
  }

  .el-button--text {
    border-color: transparent;
    background: transparent;
    color: var(--el-color-primary);
  }

  :deep(.table_header_cell) {
    text-align: center;
    background-color: #f5f7fa;
    color: #303133;
  }

  :deep(.table_row) {
    height: 50px !important;
  }

  :deep(.table_cell) {
    user-select: text;
    text-align: center;
    font-size: 14px;
    color: #000;
  }

}


</style>
